﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

using SharpBroadcast;

namespace WebVideoServer
{
    public partial class MainForm : Form
    {
        private IMediaServer m_VideoServer = null;
        private IMediaServer m_AudioServer = null;

        public MainForm()
        {
            InitializeComponent();

            if (m_VideoServer == null) m_VideoServer = new MediaServer<MpegHandler>(CommonLog.GetLogger());
            if (m_AudioServer == null) m_AudioServer = new MediaServer<Mp3Handler>(CommonLog.GetLogger());

            if (m_VideoServer != null) m_VideoServer.SetClientValidator(new WebClientValidator());
            if (m_AudioServer != null) m_AudioServer.SetClientValidator(new WebClientValidator());
        }

        public static DialogResult InputBox(string title, string promptText, ref string value)
        {
            Form form = new Form();
            Label label = new Label();
            TextBox textBox = new TextBox();
            Button buttonOk = new Button();
            Button buttonCancel = new Button();

            form.Text = title;
            label.Text = promptText;
            textBox.Text = value;

            buttonOk.Text = "OK";
            buttonCancel.Text = "Cancel";
            buttonOk.DialogResult = DialogResult.OK;
            buttonCancel.DialogResult = DialogResult.Cancel;

            label.SetBounds(9, 20, 372, 13);
            textBox.SetBounds(12, 36, 372, 20);
            buttonOk.SetBounds(228, 72, 75, 23);
            buttonCancel.SetBounds(309, 72, 75, 23);

            label.AutoSize = true;
            textBox.Anchor = textBox.Anchor | AnchorStyles.Right;
            buttonOk.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;
            buttonCancel.Anchor = AnchorStyles.Bottom | AnchorStyles.Right;

            form.ClientSize = new Size(396, 107);
            form.Controls.AddRange(new Control[] { label, textBox, buttonOk, buttonCancel });
            form.ClientSize = new Size(Math.Max(300, label.Right + 10), form.ClientSize.Height);
            form.FormBorderStyle = FormBorderStyle.FixedDialog;
            form.StartPosition = FormStartPosition.CenterScreen;
            form.MinimizeBox = false;
            form.MaximizeBox = false;
            form.AcceptButton = buttonOk;
            form.CancelButton = buttonCancel;

            DialogResult dialogResult = form.ShowDialog();
            value = textBox.Text;
            return dialogResult;
        }

        private void Log(string text)
        {
            mmLogger.AppendText("[" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "] " + text + Environment.NewLine);
            mmLogger.SelectionStart = mmLogger.Text.Length;
            mmLogger.ScrollToCaret();
        }

        public void LogMsg(string msg)
        {
            Invoke((Action)(() =>
            {
                Log(msg);
            }));
        }

        private void MainForm_Load(object sender, EventArgs e)
        {
            try
            {
                ServerSetting videoSetting = ServerSetting.Reload(CommonLog.GetLogger(), "Video");

                listWhitelist.Items.Clear();
                foreach (var address in videoSetting.InputWhitelist) listWhitelist.Items.Add(address);

                m_VideoServer.OutputBufferSize = videoSetting.OutputBufferSize;
                m_VideoServer.OutputQueueSize = videoSetting.OutputQueueSize;

                m_VideoServer.CacheQueueSize = videoSetting.CacheQueueSize;

                m_VideoServer.Start(videoSetting.InputPort, videoSetting.OutputPort, videoSetting.InputWhitelist);

                if (m_VideoServer.IsWorking())
                {
                    LogMsg("Video Server is working on port " + m_VideoServer.InputPort + " (input) and port " + m_VideoServer.OutputPort + " (output) ... ");
                }

                if (m_AudioServer != null)
                {
                    bool needAudio = false;
                    try
                    {
                        var appSettings = ConfigurationManager.AppSettings;
                        var allKeys = appSettings.AllKeys;
                        if (allKeys.Contains("EnableAudio")) needAudio = Convert.ToBoolean(appSettings["EnableAudio"]);
                    }
                    catch { }

                    if (needAudio)
                    {
                        ServerSetting audioSetting = ServerSetting.Reload(CommonLog.GetLogger(), "Audio");

                        m_AudioServer.OutputBufferSize = audioSetting.OutputBufferSize;
                        m_AudioServer.OutputQueueSize = audioSetting.OutputQueueSize;

                        m_AudioServer.CacheQueueSize = audioSetting.CacheQueueSize;

                        m_AudioServer.Start(audioSetting.InputPort, audioSetting.OutputPort, videoSetting.InputWhitelist);

                        if (m_AudioServer.IsWorking())
                        {
                            LogMsg("Audio Server is working on port " + m_AudioServer.InputPort + " (input) and port " + m_AudioServer.OutputPort + " (output) ... ");
                        }
                    }
                }

                timerRefreshInfo.Enabled = true;
                timerRefreshInfo.Start();
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
            }
        }

        private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            if (MessageBox.Show("Are you sure you want to quit ?", this.Text, MessageBoxButtons.YesNo) == DialogResult.Yes)
            {
                if (m_VideoServer != null && m_VideoServer.IsWorking()) m_VideoServer.Stop();
                if (m_AudioServer != null && m_AudioServer.IsWorking()) m_AudioServer.Stop();
                timerRefreshInfo.Enabled = false;
                e.Cancel = false;
            }
            else
            {
                e.Cancel = true;
            }
        }

        private void MainForm_Resize(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
            }
        }

        private void timerRefreshInfo_Tick(object sender, EventArgs e)
        {
            if (!this.Visible) return;
            List<MediaChannelState> states = new List<MediaChannelState>();
            if (m_VideoServer != null && m_VideoServer.IsWorking())
            {
                states.AddRange(m_VideoServer.GetChannelStates());
            }
            if (m_AudioServer != null && m_AudioServer.IsWorking())
            {
                states.AddRange(m_AudioServer.GetChannelStates());
            }
            olvClients.SetObjects(states);
        }

        private void notifyIconMain_DoubleClick(object sender, EventArgs e)
        {
            this.Show();
            this.WindowState = FormWindowState.Normal;
        }

        private void menuNotify_ItemClicked(object sender, ToolStripItemClickedEventArgs e)
        {
            if (e.ClickedItem.Tag.ToString() == "1")
            {
                this.Show();
                this.WindowState = FormWindowState.Normal;
            }
            else if (e.ClickedItem.Tag.ToString() == "2")
            {
                Task.Factory.StartNew(() =>
                {
                    Invoke((Action)(() =>
                    {
                        this.Close();
                    }));
                });
            }
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            string address = "";
            if (InputBox("Add new IP to whitelist", "IP Address", ref address) == DialogResult.OK)
            {
                if (address.Trim().Length > 0)
                {
                    listWhitelist.Items.Add(address.Trim());

                    List<string> list = new List<string>();
                    foreach (var item in listWhitelist.Items) list.Add(item.ToString());
                    list.Add(address.Trim());

                    if (m_VideoServer != null) m_VideoServer.SetSourceWhitelist(list);
                    if (m_AudioServer != null) m_AudioServer.SetSourceWhitelist(list);
                }
            }
        }

        private void btnDel_Click(object sender, EventArgs e)
        {
            string address = "";
            if (listWhitelist.SelectedIndex >= 0) address = listWhitelist.Items[listWhitelist.SelectedIndex].ToString();
            if (address.Length > 0)
            {
                if (MessageBox.Show("Are you sure you want to remove IP " + address + " from the whilelist ?",
                    this.Text, MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    listWhitelist.Items.RemoveAt(listWhitelist.SelectedIndex);

                    List<string> list = new List<string>();
                    foreach (var item in listWhitelist.Items) list.Add(item.ToString());

                    if (m_VideoServer != null) m_VideoServer.SetSourceWhitelist(list);
                    if (m_AudioServer != null) m_AudioServer.SetSourceWhitelist(list);
                }
            }
        }

        
    }
}
